﻿using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraGrid.Columns;
using Inaction.Criteria;
using Inaction.Mapping;
using Inaction.UI.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Inaction.UI.Settings
{
    public class ForeignKeyLueSetting
    {
        public static void SetProperties()
        {
            var bindingSources = ComponentCache.GetComponent<BindingSource>();
            List<BindingSource> criteriaSources = new List<BindingSource>();
            List<BindingSource> entitySources = new List<BindingSource>();
            #region 数据源
            foreach (var b in bindingSources)
            {
                var t = b.DataSource as Type;
                if (t == null) continue;
                var type = typeof(Inaction.Rule.EnumDescriptionList);
                if (t.Assembly.FullName == type.Assembly.FullName && t.FullName == type.FullName) continue;

                if (t.IsSubclassOf(typeof(Criteria.CriteriaBase)))
                {
                    criteriaSources.Add(b);
                }
                else if (t.GetInterface(typeof(Inaction.Core.ISavable).FullName) != null)
                {
                    entitySources.Add(b);
                }
            }
            #endregion

            #region 业务类
            foreach (var b in entitySources)
            {
                var t = b.DataSource as Type;
                t = BindingHelper.GetListItemType(b);
                foreach (Binding binding in b.CurrencyManager.Bindings)
                {
                    if (binding.Control is LookUpEditBase)
                    {
                        var c = binding.Control as LookUpEditBase;
                        if (c.Properties.DataSource != null) continue;
                        var property = t.GetProperty(binding.BindingMemberInfo.BindingMember);
                        var pType = property.PropertyType;
                        if (pType.IsValueType)
                        {
                            if (pType.IsGenericType)
                            {
                                pType = System.Nullable.GetUnderlyingType(pType);
                            }
                        }
                        if (pType != typeof(Guid)) continue;
                        var classInfo = ClassInfo.LoadInfo(t);
                        if (classInfo == null) continue;
                        var propertyInfo = classInfo.ColumnProperties.Values.FirstOrDefault(p => p.Name == property.Name);
                        if (propertyInfo == null || propertyInfo.Column == null || !propertyInfo.Column.IsForeignKey) continue;

                        var foreignKey = propertyInfo.Column.Table.ForeignKeys.FirstOrDefault(p => p.Column == propertyInfo.Column);
                        var foreignBs = TableClassTypeHelper.GetClassBindingSource(foreignKey.ReferenceTable.Name);
                        c.Properties.DataSource = foreignBs;

                        var foreignType = BindingHelper.GetListItemType(foreignBs);
                        var foreignClassInfo = ClassInfo.LoadInfo(foreignType);

                        var nameColumns = foreignClassInfo.NameProperties.Where(p => p.Value.Name.EndsWith("Name", StringComparison.OrdinalIgnoreCase));
                        if (nameColumns.Count() > 0)
                        {
                            c.Properties.DisplayMember = nameColumns.First().Value.Name;
                        }
                        c.Properties.ValueMember = foreignClassInfo.PrimaryKey.Name;
                        var codeColumns = foreignClassInfo.NameProperties.Where(p => p.Value.Name.EndsWith("Code", StringComparison.OrdinalIgnoreCase));
                        if (c is LookUpEdit)
                        {
                            var lue = c as LookUpEdit;
                            lue.Properties.Columns.Clear();
                            foreach (var codeColumn in codeColumns)
                            {
                                lue.Properties.Columns.Add(new LookUpColumnInfo(codeColumn.Value.Name, codeColumn.Value.DisplayName));
                            }
                            foreach (var nameColumn in nameColumns)
                            {
                                lue.Properties.Columns.Add(new LookUpColumnInfo(nameColumn.Value.Name, nameColumn.Value.DisplayName));
                            }
                        }
                        else if (c is GridLookUpEdit)
                        {
                            var glue = c as GridLookUpEdit;
                            glue.Properties.View.Columns.Clear();
                            foreach (var codeColumn in codeColumns)
                            {
                                glue.Properties.View.Columns.AddVisible(codeColumn.Value.Name);
                            }
                            foreach (var nameColumn in nameColumns)
                            {
                                glue.Properties.View.Columns.AddVisible(nameColumn.Value.Name);
                            }
                        }
                        else if (c is TreeListLookUpEdit)
                        {
                            var tlue = c as TreeListLookUpEdit;
                            tlue.Properties.TreeList.Columns.Clear();
                            tlue.Properties.TreeList.KeyFieldName = classInfo.PrimaryKey.Name;
                            var forgignKey = classInfo.Table.ForeignKeys.FirstOrDefault(p => p.ReferenceTable.Name.Equals(classInfo.TableName, StringComparison.OrdinalIgnoreCase));
                            if (forgignKey != null)
                            {
                                tlue.Properties.TreeList.ParentFieldName = forgignKey.Name;
                            }
                            foreach (var codeColumn in codeColumns)
                            {
                                tlue.Properties.TreeList.Columns.AddField(codeColumn.Value.Name);
                            }
                            foreach (var nameColumn in nameColumns)
                            {
                                tlue.Properties.TreeList.Columns.AddField(nameColumn.Value.Name);
                            }
                        }
                    }
                }
            }
            #endregion

            #region 查询类
            foreach (var b in criteriaSources)
            {
                var t = b.DataSource as Type;
                foreach (Binding binding in b.CurrencyManager.Bindings)
                {
                    var bindingInfo = BarManagerDesigner.WorkingBarManager.BindingInfos.FirstOrDefault(p => p.CriteriaBindingSource == b);
                    if (bindingInfo == null) continue;
                    if (binding.Control is LookUpEditBase)
                    {
                        var c = binding.Control as LookUpEditBase;
                        if (c.Properties.DataSource != null) continue;
                        var property = t.GetProperty(binding.BindingMemberInfo.BindingMember);
                        var pType = property.PropertyType;
                        if (pType.IsValueType)
                        {
                            if (pType.IsGenericType)
                            {
                                pType = System.Nullable.GetUnderlyingType(pType);
                            }
                        }
                        if (pType != typeof(Guid)) continue;

                        var bs = bindingInfo.BindingSource;
                        var entityType = BindingHelper.GetListItemType(bs);
                        var classInfo = ClassInfo.LoadInfo(entityType);
                        if (classInfo == null) continue;

                        var criteriaField = CriteriaBase.GetSimilarFieldCriteriaFieldAttribute(t, property.Name);
                        if (criteriaField == null || classInfo.ColumnProperties.ContainsKey(criteriaField.ColumnName)) continue;

                        var propertyInfo = classInfo.ColumnProperties[criteriaField.ColumnName];
                        if (propertyInfo.Column == null || !propertyInfo.Column.IsForeignKey) continue;
                        var foreignKey = propertyInfo.Column.Table.ForeignKeys.FirstOrDefault(p => p.Column == propertyInfo.Column);
                        var foreignBs = TableClassTypeHelper.GetClassBindingSource(foreignKey.ReferenceTable.Name);
                        c.Properties.DataSource = foreignBs;

                        var foreignType = BindingHelper.GetListItemType(foreignBs);
                        var foreignClassInfo = ClassInfo.LoadInfo(foreignType);
                        var nameColumns = foreignClassInfo.NameProperties.Where(p => p.Value.Name.EndsWith("Name", StringComparison.OrdinalIgnoreCase));
                        var codeColumns = foreignClassInfo.NameProperties.Where(p => p.Value.Name.EndsWith("Code", StringComparison.OrdinalIgnoreCase));
                        if (nameColumns.Count() > 0)
                        {
                            c.Properties.DisplayMember = nameColumns.First().Value.Name;
                        }
                        c.Properties.ValueMember = classInfo.PrimaryKey.Name;
                        if (c is LookUpEdit)
                        {
                            var lue = c as LookUpEdit;
                            lue.Properties.Columns.Clear();
                            foreach (var codeColumn in codeColumns)
                            {
                                lue.Properties.Columns.Add(new LookUpColumnInfo(codeColumn.Value.Name, codeColumn.Value.DisplayName));
                            }
                            foreach (var nameColumn in nameColumns)
                            {
                                lue.Properties.Columns.Add(new LookUpColumnInfo(nameColumn.Value.Name, nameColumn.Value.DisplayName));
                            }
                        }
                        else if (c is GridLookUpEdit)
                        {
                            var glue = c as GridLookUpEdit;
                            glue.Properties.View.Columns.Clear();
                            foreach (var codeColumn in codeColumns)
                            {
                                glue.Properties.View.Columns.AddVisible(codeColumn.Value.Name);
                            }
                            foreach (var nameColumn in nameColumns)
                            {
                                glue.Properties.View.Columns.AddVisible(nameColumn.Value.Name);
                            }
                        }
                        else if (c is TreeListLookUpEdit)
                        {
                            var tlue = c as TreeListLookUpEdit;
                            tlue.Properties.TreeList.Columns.Clear();
                            tlue.Properties.TreeList.KeyFieldName = classInfo.PrimaryKey.Name;
                            var forgignKey = classInfo.Table.ForeignKeys.FirstOrDefault(p => p.ReferenceTable.Name.Equals(classInfo.TableName, StringComparison.OrdinalIgnoreCase));
                            if (forgignKey != null)
                            {
                                tlue.Properties.TreeList.ParentFieldName = forgignKey.Name;
                            }
                            foreach (var codeColumn in codeColumns)
                            {
                                tlue.Properties.TreeList.Columns.AddField(codeColumn.Value.Name);
                            }
                            foreach (var nameColumn in nameColumns)
                            {
                                tlue.Properties.TreeList.Columns.AddField(nameColumn.Value.Name);
                            }
                        }
                    }
                }
            }
            #endregion
        }
    }
}
